/**Clase que genera la interfaz de el programa.
 *
 */

package InterfazPantera;
import java.io.IOException;
import org.jdesktop.application.*;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import javax.swing.tree.*;
import CheckTree.*;
import Algoritmo.*;
import Grafica.Grafica;
import Grafica.Vertice;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.Enumeration;
import org.jdesktop.application.Action;

public class PanteraView extends FrameView implements ServiciosAlgoritmo,
java.io.Serializable{

    private static final long serialVersionUID = 2475628602268627687L;
    
    private DefaultMutableTreeNode  raiz =
            new DefaultMutableTreeNode("Listas de vértices");
    private Algoritmo alg;
    private JLabel[]pasos;
    private static long ultimoAcceso;
    private int contador;

    public PanteraView(SingleFrameApplication app) {
        super(app);
        ultimoAcceso = System.currentTimeMillis();
        initComponents();
        cTM = new CheckTreeManager(jtArbol);
        JPContenedor.setSize(1070, 650);
        JPContenedor.updateUI();
        jTPOpciones.setSelectedIndex(0);
        seleccionador.add("Seleccione algoritmo");
        seleccionador.add("Caminos eulerianos");
        seleccionador.add("BFS");
        seleccionador.add("DFS");
        seleccionador.add("Dijkstra");
        jtArbol.setEditable(true);
        agregaVerticeMouseClicked(null);
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = PanteraApp.getApplication().getMainFrame();
            aboutBox = new PanteraAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        PanteraApp.getApplication().show(aboutBox);
    }

    /**Regresa los pesos de la gráfica introducidos por el usuario
     *
     * @return
     */
    public int[][] getPesos(){
        return cTM.getPesos();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")

    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        JPContenedor = new javax.swing.JPanel();
        seleccionador = new java.awt.Choice();
        btPasos = new javax.swing.JButton();
        jTPOpciones = new javax.swing.JTabbedPane();
        jsArbol = new javax.swing.JScrollPane();
        jtArbol = new javax.swing.JTree(raiz);
        pEtiquetas = new javax.swing.JPanel();
        panelVistaPrevia = new javax.swing.JPanel();
        jSVistaPrevia = new javax.swing.JScrollPane();
        lbGrafica = new javax.swing.JLabel();
        jPbotones = new javax.swing.JPanel();
        btElimVert = new javax.swing.JButton();
        agregaVertice = new javax.swing.JButton();
        btDibuja = new javax.swing.JButton();
        spInfAlg = new javax.swing.JScrollPane();
        taIA = new javax.swing.JTextArea();
        btReducir = new javax.swing.JButton();
        btG = new javax.swing.JButton();
        tFGC = new javax.swing.JTextField();
        btC = new javax.swing.JButton();
        jFrame1 = new javax.swing.JFrame();
        jFrame2 = new javax.swing.JFrame();

        JPContenedor.setMaximumSize(new java.awt.Dimension(1024, 800));
        JPContenedor.setMinimumSize(new java.awt.Dimension(1024, 800));
        JPContenedor.setName("JPContenedor"); // NOI18N
        JPContenedor.setPreferredSize(new java.awt.Dimension(1024, 800));
        JPContenedor.setVerifyInputWhenFocusTarget(false);

        seleccionador.setName("seleccionador"); // NOI18N
        seleccionador.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                seleccionadorItemStateChanged(evt);
            }
        });

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(InterfazPantera.PanteraApp.class).getContext().getResourceMap(PanteraView.class);
        btPasos.setText(resourceMap.getString("btPasos.text")); // NOI18N
        btPasos.setEnabled(false);
        btPasos.setName("btPasos"); // NOI18N
        btPasos.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btPasosMouseClicked(evt);
            }
        });

        jTPOpciones.setName("jTPOpciones"); // NOI18N
        jTPOpciones.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jTPOpcionesStateChanged(evt);
            }
        });

        jsArbol.setName("jsArbol"); // NOI18N

        jtArbol.setName("jtArbol");
        jsArbol.setViewportView(jtArbol);

        jTPOpciones.addTab(resourceMap.getString("jsArbol.TabConstraints.tabTitle"), jsArbol); // NOI18N

        pEtiquetas.setBackground(resourceMap.getColor("pEtiquetas.background")); // NOI18N
        pEtiquetas.setAutoscrolls(true);
        pEtiquetas.setMaximumSize(new java.awt.Dimension(597, 600));
        pEtiquetas.setName("pEtiquetas"); // NOI18N
        pEtiquetas.setPreferredSize(new java.awt.Dimension(416, 405));

        org.jdesktop.layout.GroupLayout pEtiquetasLayout = new org.jdesktop.layout.GroupLayout(pEtiquetas);
        pEtiquetas.setLayout(pEtiquetasLayout);
        pEtiquetasLayout.setHorizontalGroup(
            pEtiquetasLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 432, Short.MAX_VALUE)
        );
        pEtiquetasLayout.setVerticalGroup(
            pEtiquetasLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 428, Short.MAX_VALUE)
        );

        jTPOpciones.addTab(resourceMap.getString("pEtiquetas.TabConstraints.tabTitle"), pEtiquetas); // NOI18N

        panelVistaPrevia.setBackground(resourceMap.getColor("panelVistaPrevia.background")); // NOI18N
        panelVistaPrevia.setForeground(resourceMap.getColor("panelVistaPrevia.foreground")); // NOI18N
        panelVistaPrevia.setMaximumSize(new java.awt.Dimension(653, 474));
        panelVistaPrevia.setMinimumSize(new java.awt.Dimension(653, 474));
        panelVistaPrevia.setName("panelVistaPrevia"); // NOI18N
        panelVistaPrevia.setPreferredSize(new java.awt.Dimension(653, 474));
        panelVistaPrevia.setRequestFocusEnabled(false);

        jSVistaPrevia.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        jSVistaPrevia.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        jSVistaPrevia.setAutoscrolls(true);
        jSVistaPrevia.setFocusTraversalPolicyProvider(true);
        jSVistaPrevia.setName("jSVistaPrevia"); // NOI18N

        lbGrafica.setText(resourceMap.getString("lbGrafica.text")); // NOI18N
        lbGrafica.setAutoscrolls(true);
        lbGrafica.setName("lbGrafica"); // NOI18N
        jSVistaPrevia.setViewportView(lbGrafica);

        org.jdesktop.layout.GroupLayout panelVistaPreviaLayout = new org.jdesktop.layout.GroupLayout(panelVistaPrevia);
        panelVistaPrevia.setLayout(panelVistaPreviaLayout);
        panelVistaPreviaLayout.setHorizontalGroup(
            panelVistaPreviaLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jSVistaPrevia, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 685, Short.MAX_VALUE)
        );
        panelVistaPreviaLayout.setVerticalGroup(
            panelVistaPreviaLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jSVistaPrevia, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 474, Short.MAX_VALUE)
        );

        jPbotones.setName("jPbotones"); // NOI18N

        btElimVert.setText(resourceMap.getString("btElimVert.text")); // NOI18N
        btElimVert.setName("btElimVert"); // NOI18N
        btElimVert.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btElimVertMouseClicked(evt);
            }
        });

        agregaVertice.setText(resourceMap.getString("agregaVertice.text")); // NOI18N
        agregaVertice.setName("agregaVertice"); // NOI18N
        agregaVertice.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                agregaVerticeMouseClicked(evt);
            }
        });

        btDibuja.setText(resourceMap.getString("btDibuja.text")); // NOI18N
        btDibuja.setName("btDibuja"); // NOI18N
        btDibuja.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btDibujaMouseClicked(evt);
            }
        });

        spInfAlg.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        spInfAlg.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        spInfAlg.setInheritsPopupMenu(true);
        spInfAlg.setName("spInfAlg"); // NOI18N
        spInfAlg.setPreferredSize(new java.awt.Dimension(437, 0));

        taIA.setColumns(20);
        taIA.setEditable(false);
        taIA.setMaximumSize(new java.awt.Dimension(437, 600));
        taIA.setMinimumSize(new java.awt.Dimension(0, 0));
        taIA.setName("taIA"); // NOI18N
        taIA.setPreferredSize(new java.awt.Dimension(0, 0));
        spInfAlg.setViewportView(taIA);

        org.jdesktop.layout.GroupLayout jPbotonesLayout = new org.jdesktop.layout.GroupLayout(jPbotones);
        jPbotones.setLayout(jPbotonesLayout);
        jPbotonesLayout.setHorizontalGroup(
            jPbotonesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPbotonesLayout.createSequentialGroup()
                .add(jPbotonesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jPbotonesLayout.createSequentialGroup()
                        .add(agregaVertice)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(btElimVert, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 148, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(btDibuja))
                    .add(spInfAlg, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 431, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPbotonesLayout.setVerticalGroup(
            jPbotonesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPbotonesLayout.createSequentialGroup()
                .add(spInfAlg, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 66, Short.MAX_VALUE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPbotonesLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(agregaVertice)
                    .add(btElimVert)
                    .add(btDibuja))
                .add(17, 17, 17))
        );

        btReducir.setText(resourceMap.getString("btReducir.text")); // NOI18N
        btReducir.setName("btReducir"); // NOI18N
        btReducir.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btReducirMouseClicked(evt);
            }
        });

        btG.setText(resourceMap.getString("btG.text")); // NOI18N
        btG.setName("btG"); // NOI18N
        btG.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btGMouseClicked(evt);
            }
        });

        tFGC.setText(resourceMap.getString("text")); // NOI18N
        tFGC.setName(""); // NOI18N

        btC.setText(resourceMap.getString("btC.text")); // NOI18N
        btC.setName("btC"); // NOI18N
        btC.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btCMouseClicked(evt);
            }
        });

        org.jdesktop.layout.GroupLayout JPContenedorLayout = new org.jdesktop.layout.GroupLayout(JPContenedor);
        JPContenedor.setLayout(JPContenedorLayout);
        JPContenedorLayout.setHorizontalGroup(
            JPContenedorLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(JPContenedorLayout.createSequentialGroup()
                .add(JPContenedorLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jTPOpciones, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 453, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(JPContenedorLayout.createSequentialGroup()
                        .add(10, 10, 10)
                        .add(jPbotones, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(JPContenedorLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(JPContenedorLayout.createSequentialGroup()
                        .add(seleccionador, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 140, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(1, 1, 1)
                        .add(btPasos)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btReducir)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(tFGC, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 92, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(btC, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 56, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(btG, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 54, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(43, 43, 43))
                    .add(panelVistaPrevia, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 685, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );
        JPContenedorLayout.setVerticalGroup(
            JPContenedorLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(JPContenedorLayout.createSequentialGroup()
                .add(JPContenedorLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(JPContenedorLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(jTPOpciones, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 474, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jPbotones, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(JPContenedorLayout.createSequentialGroup()
                        .add(29, 29, 29)
                        .add(panelVistaPrevia, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(JPContenedorLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(JPContenedorLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                .add(tFGC, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .add(btC)
                                .add(btG)
                                .add(btPasos)
                                .add(btReducir))
                            .add(seleccionador, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))
                .addContainerGap(197, Short.MAX_VALUE))
        );

        jFrame1.setName("jFrame1"); // NOI18N

        org.jdesktop.layout.GroupLayout jFrame1Layout = new org.jdesktop.layout.GroupLayout(jFrame1.getContentPane());
        jFrame1.getContentPane().setLayout(jFrame1Layout);
        jFrame1Layout.setHorizontalGroup(
            jFrame1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 400, Short.MAX_VALUE)
        );
        jFrame1Layout.setVerticalGroup(
            jFrame1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 300, Short.MAX_VALUE)
        );

        jFrame2.setName("jFrame2"); // NOI18N

        org.jdesktop.layout.GroupLayout jFrame2Layout = new org.jdesktop.layout.GroupLayout(jFrame2.getContentPane());
        jFrame2.getContentPane().setLayout(jFrame2Layout);
        jFrame2Layout.setHorizontalGroup(
            jFrame2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 400, Short.MAX_VALUE)
        );
        jFrame2Layout.setVerticalGroup(
            jFrame2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 300, Short.MAX_VALUE)
        );

        setComponent(JPContenedor);
    }// </editor-fold>//GEN-END:initComponents

    /**Regresa el programa al área de diseño
     *
     */
    public void regresaADiseño(){
        jTPOpciones.setSelectedIndex(0);
        JPContenedor.updateUI();
        btPasos.setEnabled(false);
        seleccionador.select(0);
    }

    /**Determina si el paso i se encuentra activo.
     * 
     * @param i - El paso que se desea saber si está activo.
     * @return <code>boolean</code> que determina el estado del paso.
     */
    public boolean esActual(int i){
        return pasos[i].getBorder()!=null;
    }


    public void dibuja(String g){
        if(g!=null){
            GraphViz.escribeGrafica(g);
            GraphViz.escribeGrafica(g,"Graf"+contador++);
            Image im = Toolkit.getDefaultToolkit().getImage("Grafica.gif");
            ImageIcon icon = new ImageIcon(im);
            lbGrafica.setIcon(icon);
            im.flush();
            icon = new ImageIcon(im);
            lbGrafica.setIcon(icon);
            im.flush();
        }
    }


    /**Marca un vértice del color indicado.
     *
     * @param v - El número del vértice a marcar.
     * @param c - El color del vértice.
     */
    public void dibuja(int v, String color){
         // Pintamos en el panel la gráfica usando graphViz.
        String grafica = cTM.generaGrafica(v,color);
        GraphViz graf = new GraphViz();
        graf.add(grafica);
        System.out.println(grafica);
        File out = new File("Grafica.gif");
        graf.writeGraphToFile(graf.getGraph(graf.getDotSource()), out);
        Image im = Toolkit.getDefaultToolkit().getImage("Grafica.gif");
        ImageIcon icon = new ImageIcon(im);
        lbGrafica.setIcon(icon);
        im.flush();
    }

    /**Dibuja la gráfica actual contenida en el <code>CheckTreeManager</code>
     *
     */
    public void dibuja(){
        dibuja(cTM.generaGrafica());
    }

    

    /**Guarda la gráfica <code>g</code> en el lenguaje de graphviz.
     * El archivo guardado tendrá el nombre que se le pasa de parámetro.
     *
     * @param nombre El nombre del archivo a guardar
     */
    public void guarda(String nombre, String g){
        File f = new File("Graficas/"+nombre+".gv");
        try{
            FileWriter fw = new FileWriter(f);
            fw.write(g);
            fw.close();
        }catch(IOException ioe){
            enviaMensaje("Hubo un problema al guardar el archivo");
        }
    }

    /**Regresa el número asociado al vértice en el nodo n
     * 
     * @param n El nodo
     * @return El entero asociado al nodo n
     */
    private int getNv(DefaultMutableTreeNode n){
       return cTM.getNv(n);
    }

    /**Elimina el nodo n de los hijos del último elemento de cada TreePath
     *
     * @param t Un arreglo de trayectorias
     * @param n El nodo a eliminar
     */
    public void eliminaNodos(Enumeration<DefaultMutableTreeNode> t,
                             DefaultMutableTreeNode n){
        while(t.hasMoreElements()){
            DefaultMutableTreeNode tmp = t.nextElement();
            eliminaNodo(tmp, n);                     
        }
    }

    /**Elimina el nodo e de los hijos de el nodo n.
     *
     * @param e El nodo a eliminar
     */
    public void eliminaNodo(DefaultMutableTreeNode n, DefaultMutableTreeNode e){
        int nV = getNv(e);
        Enumeration<DefaultMutableTreeNode> enu = n.children();
        while(enu.hasMoreElements()){
            DefaultMutableTreeNode act = enu.nextElement();
            if(getNv(act)==nV)
                n.remove(act);
        }
    }


    /**Renombra los vértices para que vayan del V0 al Vi,
     * con i=número de vértices - 1
     *
     * @param n La raíz del árbol
     */
    private void renombraTodos(DefaultMutableTreeNode n){
        Enumeration<DefaultMutableTreeNode> en =
                (Enumeration<DefaultMutableTreeNode>)n.children();
        for(int i=0;en.hasMoreElements();i++){
            DefaultMutableTreeNode tmp =  en.nextElement();
            tmp.setUserObject("V"+i);
            Enumeration<DefaultMutableTreeNode> enT =
                    (Enumeration<DefaultMutableTreeNode>)tmp.children();
            for(int j=0;enT.hasMoreElements();j++)
                if(i!= j){
                    tmp = enT.nextElement();
                    tmp.setUserObject("V"+j);
                }            
        }
    }

    /**Revisa si el nodo que se e pasa de parámetro se encuentra en la <code>
     * TreePath</code> que se le pasa de parámetro
     *
     * @param n Un nodo
     * @param t Una trayectoria
     * @return boolean 
     */
    public boolean estaEnT(DefaultMutableTreeNode n, TreePath t){
        boolean b0 = cTM.getNv((DefaultMutableTreeNode)t.
                getLastPathComponent())==cTM.getNv(n);
        boolean b1 = false;
        if(t.getPathCount()==3)
            b1 = cTM.getNv((DefaultMutableTreeNode)t.getPathComponent(1))
                ==cTM.getNv(n);
        boolean b2 = cTM.getNv((DefaultMutableTreeNode)t.getPathComponent(0))
                ==cTM.getNv(n);
        return b0 || b1 || b2;
    }


    public String generaGrafica(int[]grados){
        return cTM.generaGrafica(grados);
    }

    public String generaGrafica(){
        return cTM.generaGrafica();
    }




    /**Genera la gráfica representada con la lista de adyacencias
     *
     * @return La gráfica actual.
     */
    public Grafica grafica(){    
       return new Grafica(cTM.getVertices());
    }



    /**Limpia el panel de desarrollo
     *
     */
    public void borraDesarrollo(){
        taIA.removeAll();
        taIA.setText("");
        taIA.setRows(0);
    }

    /**Agrega un nuevo suceso al desarrollo
     * 
     * @param suceso La nueva cadena que se agrega al final del panel que
     * muestra el desarrollo del algoritmo
     */
    public void agregaADesarrollo(String suceso){
        taIA.append(suceso);        
        taIA.setRows(taIA.getText().split("\n").length);
    }

    /**Cambia la etiqueta del paso actual al siguiente.
     *
     * @param a El número de etiqueta actual
     * @param b El número de la etiqueta que tiene el siguiente paso a ejecutar,
     * se marca en amarillo
     */
    public void cambiaPaso(int a, int b){
        pasos[a].setBorder(null);
        pasos[b].setBorder(new  javax.swing.border.LineBorder(Color.yellow, 1));
    }

    /**Desactiva el paso que se le pasa de parámetro
     *
     * @param a El número del paso a desactivar
     */
    public void desactiva(int a){
        pasos[a].setBorder(null);
    }


    /**Determina si un paso es nulo.
     *
     * @param p - El paso que se desea saber si es nulo.
     * @return <code>Boolean</code>, indica si el paso está marcado.
     */
    public boolean nulo(int p){
        return pasos[p].getBorder()==null;
    }


    /**Marca un vértice del color indicado.
     *
     * @param v - El número del vértice a marcar.
     * @param c - El color del vértice.
     */
    public void marcaVertice(int v, String c){
       dibuja(v,c);
    }

    public void agregaPasos(String alg){
        pEtiquetas.removeAll();
        pEtiquetas.updateUI();
        File carp = new File(alg);
        String[]archivos = carp.list();
        pasos = new JLabel[archivos.length+1];      
        int i = 0;
        for(String cad:archivos){
           if(cad.substring(cad.length()-3).equals("jpg")){
               Image im = Toolkit.getDefaultToolkit().getImage(alg+"/"+cad);
               JLabel lb = new JLabel();
               lb.setIcon(new ImageIcon(im)); 
               pEtiquetas.add(lb);
               im.flush();
               lb.setBounds(0,lb.getY()+(i>0 ? (int)
                (pasos[i-1].getY()+pasos[i-1].getIcon().getIconHeight())
                : -2)+2,pEtiquetas.getWidth()-6,lb.getIcon().getIconHeight());
               pasos[i++] = lb;
           }
        }
        pasos[i] = lbGrafica;
    }

    /**Envía un mensaje al usuario.
     *
     * @param mensaje El mensaje que se enviará.
     */
    public void enviaMensaje(String mensaje){
        JOptionPane.showMessageDialog(btPasos,mensaje);
    }
     
    private void jTPOpcionesStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jTPOpcionesStateChanged
        Component[]comps = {agregaVertice,btElimVert,btDibuja,spInfAlg,
        seleccionador,btPasos};

        boolean diseno = jTPOpciones.getSelectedIndex()==0;
        if(!diseno){
        //    cbVI.add("1");
          //  cbVI.add("2");
        }
        for(int i=0;i<3;i++)
            comps[i].setVisible(diseno);
        for(int i=3;i<comps.length;i++)
            comps[i].setVisible(!diseno);
        
       // seleccionador.select(0);

}//GEN-LAST:event_jTPOpcionesStateChanged


    private void btCMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btCMouseClicked
        // Read from disk using FileInputStream
        try{
           
            FileInputStream f_in = new
                    FileInputStream("ObjetosGP/"+tFGC.getText()+"CTM.data");

            // Read object using ObjectInputStream
            ObjectInputStream obj_in =
                    new ObjectInputStream(f_in);

            // Read an object
            convierte((Grafica)obj_in.readObject());
            //alg.setG((Grafica)obj_in.readObject());
            //dibuja();
        enviaMensaje("Se ha cargado exitósamente la gráfica");
        }catch(IOException s){
            enviaMensaje("Ocurrió un error al cargar el archivo," +
                    "asegúrese de que existe el archivo e intente de nuevo");
        } catch(ClassNotFoundException s){
            enviaMensaje("Ocurrió un error al cargar el archivo");
        } catch(Exception s){
            enviaMensaje("Ocurrió un error al cargar el archivo");
        }
}//GEN-LAST:event_btCMouseClicked

    private void btDibujaMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btDibujaMouseClicked
        dibuja(cTM.generaGrafica());
}//GEN-LAST:event_btDibujaMouseClicked

    private void agregaVerticeMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_agregaVerticeMouseClicked

        int nV = raiz.getChildCount();
        raiz.add(new DefaultMutableTreeNode("V"+nV));
        DefaultMutableTreeNode n = (DefaultMutableTreeNode)raiz.getLastChild();

        for(int i=0;i<nV;i++){
            n.add(new DefaultMutableTreeNode("V"+i));
            ((DefaultMutableTreeNode)raiz.getChildAt(i)).
                    add(new DefaultMutableTreeNode("V"+nV));
        }
        cTM.modificaLista(new TreePath(new TreeNode[]{raiz,n}), true);
        
        jtArbol.updateUI();

        /*for(int i=0;i<raiz.getChildCount();i++)
            jtArbol.expandRow(i);
        jtArbol.updateUI();*/
}//GEN-LAST:event_agregaVerticeMouseClicked

    private void btElimVertMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btElimVertMouseClicked
        //El ultimo nodo de las trayectorias seleccionadas seleccionado es
        //el que se tiene que eliminar
        TreePath[]checkedPaths = jtArbol.getSelectionModel().
                getSelectionPaths();

        for(TreePath tp : checkedPaths){
            eliminaNodo(raiz,(DefaultMutableTreeNode)tp.
            getLastPathComponent());
            eliminaNodos(raiz.children(),(DefaultMutableTreeNode)tp.
            getLastPathComponent());
        }

        //Este será un temporal para eliminar los nodos
        TreePath[]selected = cTM.getSelectionModel().getSelectionPaths();

        if(selected!=null)
        for(TreePath tp : checkedPaths){
            DefaultMutableTreeNode el = (DefaultMutableTreeNode)
                    tp.getLastPathComponent();

            TreePath[]tmp = selected;            
            
            for(TreePath t : tmp)
                if(estaEnT(el, t))
                    cTM.getSelectionModel().removeSelectionPath(t);
        }

        renombraTodos(raiz);
        jtArbol.updateUI();
}//GEN-LAST:event_btElimVertMouseClicked

    private void seleccionadorItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_seleccionadorItemStateChanged
        btPasos.setVisible(true);
        btPasos.setEnabled(seleccionador.getSelectedIndex()!=0);
        btPasos.setText("Comienza algoritmo");
        switch(seleccionador.getSelectedIndex()){
            case 0:
                break;
            case 1:
                alg = new CicloEuleriano(this);
                break;
            case 2:
                alg = new BFS(this);
                break;
            case 3:
                alg = new DFS(this);
                break;
            case 4:
                alg = new Dijkstra(this);
                break;
        }
}//GEN-LAST:event_seleccionadorItemStateChanged

    private void btPasosMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btPasosMouseClicked
        btPasos.setText("Siguiente paso");
        alg.ejecutaPaso();
}//GEN-LAST:event_btPasosMouseClicked

    private void btReducirMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btReducirMouseClicked
        File f = new File("Grafica.gif");
        Long lm = f.lastModified();
        Date d = new Date(lm);
        if(raiz.getChildCount()>0 && ultimoAcceso < lm){
            Image im = Toolkit.getDefaultToolkit().getImage("Grafica.gif");
            im = im.getScaledInstance(panelVistaPrevia.getWidth()-20,
                    panelVistaPrevia.getHeight()-20, 3);
            lbGrafica.setIcon(new ImageIcon(im));
            im.flush();
        }
}//GEN-LAST:event_btReducirMouseClicked

    private void btGMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btGMouseClicked
        /*String grafica = this.jTPOpciones.getSelectedIndex()==0 ?
                         cTM.generaGrafica() : alg.generaGrafica();*/
        String grafica = grafica().generaGrafica();
        this.guarda(tFGC.getText(), grafica);
        try{
            FileOutputStream f_out = new
                    FileOutputStream("ObjetosGP/"+tFGC.getText()+"CTM.data");
            ObjectOutputStream obj_out = new ObjectOutputStream(f_out);
            obj_out.writeObject( grafica() );
            enviaMensaje("Se ha guardado la gráfica: "+ tFGC.getText());
        }catch(Exception es){
            enviaMensaje("Ocurrió un error al guardar la gráfica, " +
                    "asegúrese de que no exista una gráfica con el " +
                    "mismo nombre.");
        }
}//GEN-LAST:event_btGMouseClicked

    /**Convierte la <code>Grafica</code> que se le pasa de parámetro a un
     * <code>CheckTreeManager</code>
     *
     * @param G
     * @return CheckTreeManager
     */
    private CheckTreeManager convierte(Grafica G){

        if(cTM.getSelectionModel()!=null){
            TreePath[]paths = cTM.getSelectionModel().getSelectionPaths();
            if(paths!=null)
                cTM.getSelectionModel().removeSelectionPaths(paths);
        }

        if(raiz!=null)
            raiz.removeAllChildren();

        for(int i=0;i<G.numV;i++)
            agregaVerticeMouseClicked(null);

        for(Vertice v: G.getVertices())
            for(Vertice u : v.ady())
                cTM.agregaTrayectoria(u.nV(), v.nV(),raiz);

        dibuja();
        jtArbol.updateUI();
        return cTM;
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel JPContenedor;
    private javax.swing.JButton agregaVertice;
    private javax.swing.JButton btC;
    private javax.swing.JButton btDibuja;
    private javax.swing.JButton btElimVert;
    private javax.swing.JButton btG;
    private javax.swing.JButton btPasos;
    private javax.swing.JButton btReducir;
    private javax.swing.JFrame jFrame1;
    private javax.swing.JFrame jFrame2;
    private javax.swing.JPanel jPbotones;
    private javax.swing.JScrollPane jSVistaPrevia;
    private javax.swing.JTabbedPane jTPOpciones;
    private javax.swing.JScrollPane jsArbol;
    private javax.swing.JTree jtArbol;
    private javax.swing.JLabel lbGrafica;
    private javax.swing.JPanel pEtiquetas;
    private javax.swing.JPanel panelVistaPrevia;
    private java.awt.Choice seleccionador;
    private javax.swing.JScrollPane spInfAlg;
    private javax.swing.JTextField tFGC;
    private javax.swing.JTextArea taIA;
    // End of variables declaration//GEN-END:variables
    private CheckTreeManager cTM;
    private JDialog aboutBox;
}